﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace NetDh.Lib
{
    public class SlowHttpTracer
    {
        public static int SlowMs = 2000;//Action执行时间超过2秒，则记录慢日志。不同项目，可修改此值。
        public static Action<string> DoLog { get; set; }

        //public static readonly string TRACERT_KEY = "_slow_http_tracer_";
        //-->过于频繁操作ConcurrentDictionary线程安全对象，不利提高并发
        //private static ConcurrentDictionary<long, SlowHttpTracer> Tracers = new ConcurrentDictionary<long, SlowHttpTracer>();

        private static long _incId = 0;
        /// <summary>
        /// 临时自增id
        /// </summary>
        public long Id { get; set; }
        /// <summary>
        /// 平台类型，e.g. Mvc,WebApi..
        /// </summary>
        public WebPlatform Type { get; set; }
        public DateTime StartTime { get; set; }
        /// <summary>
        /// 总花费的毫秒数
        /// </summary>
        public double TotalMs { get; set; }
        public string Url { get; set; }
        public string Method { get; set; }
        public string Parmas { get; set; }
        public UserToken Token { get; set; }

        /// <summary>
        /// 确认是否记录慢日志。
        /// </summary>
        /// <param name="isTimers">是否是定时器调用</param>
        public static void CheckLog(UserToken token, WebPlatform type)
        {
            var totalMs = (DateTime.Now - token._HttpTime).TotalMilliseconds;
            if (totalMs > SlowMs)
            {
                //慢执行时，才创建对象。
                var tracer = Create(type);
                tracer.StartTime = token._HttpTime;
                tracer.Token = token;
                tracer.TotalMs = totalMs;
                DoLog?.Invoke(tracer.ToString());
            }
        }
        /// <summary>
        /// 根据当前HttpContext.Current上下文环境，创建SlowHttpTracer对象。
        /// </summary>
        private static SlowHttpTracer Create(WebPlatform type)
        {
            var tracer = new SlowHttpTracer();
            tracer.Id = Interlocked.Increment(ref _incId);//只有慢执行时才会进来，因此并不会频繁调用。
            tracer.Type = type;
            var request = HttpContext.Current.Request;
            tracer.Url = request.Url.AbsoluteUri;
            tracer.Method = request.HttpMethod.ToUpper();
            if (tracer.Method == "GET")
            {
                tracer.Parmas = request.QueryString.ToString();
            }
            else if (tracer.Method == "POST")
            {
                tracer.Parmas = request.Form.ToString();
            }
            return tracer;
        }

        public override string ToString()
        {
            return "[SlowAction]" + JsonConvert.SerializeObject(this);
        }
    }
    public enum WebPlatform
    {
        mvc = 0,
        api = 1,
    }
    #region //支持“防止请求开始后，因超时，无处理请求结束。这种情况是要记录慢日志中。”，这种情况不是很必要，又很频繁操作ConcurrentDictionary线程安全对象
    //public class SlowHttpTracer
    //{
    //    public static int SlowMs = 2000;//Action执行时间超过2秒，则记录慢日志。不同项目，可修改此值。
    //    public static Action<string> DoLog { get; set; }

    //    public static readonly string TRACERT_KEY = "_slow_http_tracer_";

    //    private static ConcurrentDictionary<long, SlowHttpTracer> Tracers = new ConcurrentDictionary<long, SlowHttpTracer>();
    //    private static long _incId = 0;
    //    #region 防止请求开始后，因超时，无处理请求结束。这种情况是要记录慢日志中。
    //    private static System.Timers.Timer timer = new System.Timers.Timer(600000);//10分钟确认一次
    //    static SlowHttpTracer()
    //    {
    //        timer.Elapsed += TimerElapsed;
    //        timer.Start();
    //    }
    //    private static void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
    //    {
    //        foreach (var tracerKv in Tracers)
    //        {
    //            var tracer = tracerKv.Value;
    //            tracer.CheckLog(true);
    //        }
    //    }
    //    #endregion
    //    /// <summary>
    //    /// 自增id
    //    /// </summary>
    //    public long Id { get; set; }
    //    /// <summary>
    //    /// 0:mvc;1:web api
    //    /// </summary>
    //    public WebPlatform Type { get; set; }
    //    public DateTime StartTime { get; set; }
    //    /// <summary>
    //    /// 总花费的毫秒数
    //    /// </summary>
    //    public double TotalMs { get; set; }
    //    public string Url { get; set; }
    //    public UserToken Token { get; set; }
    //    public string Method { get; set; }
    //    public string Parmas { get; set; }

    //    public static SlowHttpTracer Create(WebPlatform type)
    //    {
    //        var tracer = new SlowHttpTracer();
    //        tracer.Id = Interlocked.Increment(ref _incId);
    //        tracer.Type = type;
    //        tracer.StartTime = DateTime.Now;
    //        tracer.Token = IdentityHttpContext.Current.Token;
    //        tracer.Url = HttpContext.Current.Request.Url.AbsoluteUri;
    //        tracer.Method = HttpContext.Current.Request.HttpMethod.ToUpper();
    //        if (tracer.Method == "GET")
    //        {
    //            tracer.Parmas = HttpContext.Current.Request.QueryString.ToString();
    //        }
    //        else if (tracer.Method == "POST")
    //        {
    //            tracer.Parmas = HttpContext.Current.Request.Form.ToString();
    //        }
    //        Tracers.TryAdd(tracer.Id, tracer);
    //        return tracer;
    //    }
    //    /// <summary>
    //    /// 确认是否记录慢日志。
    //    /// </summary>
    //    /// <param name="isTimers">是否是定时器调用</param>
    //    public void CheckLog(bool isTimers = false)
    //    {
    //        var totalMs = (DateTime.Now - StartTime).TotalMilliseconds;
    //        SlowHttpTracer tmp;
    //        if (totalMs > SlowMs)
    //        {
    //            TotalMs = totalMs;
    //            DoLog(ToString());
    //            Tracers.TryRemove(Id, out tmp);
    //        }
    //        else if (!isTimers)//如果不是定时器调用，则才可以删除确认过的数据。因为定时器到点时，可能刚好有些请求刚开始。
    //        {
    //            Tracers.TryRemove(Id, out tmp);
    //        }
    //    }
    //    public override string ToString()
    //    {
    //        return "[SlowAction]" + JsonConvert.SerializeObject(this);
    //    }
    //}
    #endregion

}
